﻿

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Autofac.Extras.DynamicProxy;
using Lk.Api.Aop;
using Lk.Common.Cache;
using Lk.Common.Helper;
using Lk.Common.Redis;
using Lk.Common.SwaggerHelp;
using Lk.IServices;
using Lk.Services;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Caching.Redis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.PlatformAbstractions;
using Swashbuckle.AspNetCore.Swagger;

namespace Lk.Api
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        // public void ConfigureServices(IServiceCollection services)
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            //：Microsoft.AspNetCore.Mvc.Versioning 1.0为默认版本
            services.AddApiVersioning((o) =>
            {
                o.ReportApiVersions = true;
                o.AssumeDefaultVersionWhenUnspecified = true;
                o.DefaultApiVersion = new ApiVersion(1, 0);

            });


            #region 缓存选择
            //  services.AddMemoryCache();
            if (ConfigHelper.GetSection("CacheConfiguration", "UseRedis") == "True")
            {
                services.AddSingleton(typeof(ICacheService), new RedisCacheService(new RedisCacheOptions
                {
                    Configuration = ConfigHelper.GetSection("CacheConfiguration", "Redis_ConnectionString"),
                    InstanceName = ConfigHelper.GetSection("CacheConfiguration", "Redis_InstanceName")

                }, 0));
            }
            else
            {
                services.AddSingleton<IMemoryCache>(factory =>
                {
                    var cache = new MemoryCache(new MemoryCacheOptions());
                    return cache;
                });
                services.AddSingleton<ICacheService, MemoryCacheService>();
            }
            #endregion
            /// 
            #region CORS 跨域配置
            services.AddCors(c =>
            {
                c.AddPolicy("AllowAnyOrigin", policy =>
                {
                    policy.AllowAnyOrigin()//允许任何源
                    .AllowAnyMethod()//允许任何方式
                    .AllowAnyHeader()//允许任何头
                    .AllowCredentials();//允许cookie
                });
                //一般采用这种方法
                //c.AddPolicy("LimitRequests", policy =>
                //{
                //    policy
                //    .WithOrigins("http://localhost:8020", "http://blog.core.xxx.com", "")//支持多个域名端口
                //    .WithMethods("GET", "POST", "PUT", "DELETE")//请求方法添加到策略
                //    .WithHeaders("authorization");//标头添加到策略
                //});

            });
            #endregion

            #region  Swagger 配置
            services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Info { Title = "MyApi", Version = "v1" });
            // Set the comments path for the Swagger JSON and UI.
            var xmlPath = Path.Combine(AppContext.BaseDirectory, "Lk.Api.xml");
            c.IncludeXmlComments(xmlPath, true);//添加控制器层注释（true表示显示控制器注释）
                                                // c.OperationFilter<AddAuthTokenHeaderParameter>(); 自定义参数
                                                // c.OperationFilter<AddAuthTokenHeaderParameter>(); 
                                                //手动高亮
                                                //添加header验证信息
                                                //c.OperationFilter<SwaggerHeader>();
            var security = new Dictionary<string, IEnumerable<string>> { { "Bearer", new string[] { } }, };
            c.AddSecurityRequirement(security);//添加一个必须的全局安全信息，和AddSecurityDefinition方法指定的方案名称要一致，这里是Bearer。
            c.AddSecurityDefinition("Bearer", new ApiKeyScheme
            {
                Description = "授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"",
                Name = "Authorization",//jwt默认的参数名称
                In = "header",//默认存放Authorization信息的位置(请求头中)
                Type = "apiKey"
            });

        });
            #endregion

            #region token 服务注册

            services.AddSingleton<IMemoryCache>(factory =>
            {
                var cache = new MemoryCache(new MemoryCacheOptions());
                return cache;
            });

            services.AddAuthorization(options =>
            {
                options.AddPolicy("Client", policy => policy.RequireRole("Client").Build());
                options.AddPolicy("Admin", policy => policy.RequireRole("Client").Build());
                options.AddPolicy("AdminOrClient", policy => policy.RequireRole("Client").Build());

            });

            #endregion

         

            #region AutoFac

            var builder = new ContainerBuilder();

            //builder.RegisterType<UserService>().As<IUserService>();

         

           // builder.RegisterType<CacheAop>();
            var assemblysService = Assembly.Load("Lk.Services");
            builder.RegisterAssemblyTypes(assemblysService).AsImplementedInterfaces();
               // InstancePerLifetimeScope().EnableInterfaceInterceptors().InterceptedBy(typeof(CacheAop));

            // .EnableInterfaceInterceptors()//对目标类型启用接口拦截。拦截器将被确定，通过在类或接口上截取属性, 或添加 InterceptedBy ()
            //.InterceptedBy(typeof(BlogLogAOP));//允许将拦截器服务的列表分配给注册。

            var assemblysRepositories = Assembly.Load("Lk.Repositories");
            builder.RegisterAssemblyTypes(assemblysRepositories).AsImplementedInterfaces();

            //var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;//获取项目路径
            //var servicesDllFile = Path.Combine(basePath, "Lk.Services.dll");//获取注入项目绝对路径
            //var assemblysServices = Assembly.LoadFile(servicesDllFile);//直接采用加载文件的方法
            //容器生成
            builder.Populate(services);
            var applicationContainer = builder.Build();


            #endregion

         
            return new AutofacServiceProvider(applicationContainer);//返回第三方ioc
            //  services.AddTransient<IUserService, UserService>();

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }
            app.UseMiddleware<JwtTokenAuth.JwtTokenAuth>();
            app.UseHttpsRedirection();
            app.UseMvc();
            app.UseStaticFiles();
            // Enable middleware to serve generated Swagger as a JSON endpoint.
            app.UseSwagger(c => { c.RouteTemplate = "swagger/{documentName}/swagger.json"; });

            app.UseSwaggerUI(c =>
            {
                //c.RoutePrefix = "swagger/ui";
                c.SwaggerEndpoint("v1/swagger.json", "Lk.Api");
            });

        }
    }
}
